import os
import json
import threading

from oj_server import settings
from .machine import Machine
import logging
logger = logging.getLogger(__name__)


class LoadBalance:
    def __init__(self, config_file=None):
        """初始化负载均衡器，加载主机配置"""
        self.machines = []  # 主机列表
        self.online_machines = []  # 在线主机索引
        self.offline_machines = []  # 离线主机索引
        self.mtx = threading.Lock()  # 互斥锁

        # 加载主机配置，默认为settings中的配置
        self.config_file = config_file or getattr(settings, 'SERVICE_MACHINES_CONF', './conf/service_machines.conf')
        self.load_config()
        logger.info(f"主机配置[{self.config_file}]加载成功")

    def load_config(self):
        """从配置文件加载主机信息"""
        if not os.path.exists(self.config_file):
            logger.fatal(f"主机配置文件[{self.config_file}]不存在")
            return False

        try:
            with open(self.config_file, 'r') as f:
                for line in f:
                    line = line.strip()
                    if not line:
                        continue

                    # 解析IP和端口
                    try:
                        ip, port = line.split(':')
                        port = int(port.strip())

                        # 创建主机对象
                        machine = Machine(ip.strip(), port)
                        self.machines.append(machine)
                        self.online_machines.append(len(self.machines) - 1)  # 添加到在线列表

                    except Exception as e:
                        logger.fatal(f"解析主机配置行[{line}]失败: {str(e)}")
                        continue
            return True
        except Exception as e:
            logger.fatal(f"加载主机配置文件[{self.config_file}]失败: {str(e)}")
            return False

    def select_machine(self):
        """选择负载最低的在线主机"""
        with self.mtx:
            if not self.online_machines:
                logger.fatal("没有在线主机")
                return None, None

            # 找到负载最低的主机
            min_load = float('inf')
            best_machine_idx = self.online_machines[0]

            for idx in self.online_machines:
                load = self.machines[idx].get_load()
                if load < min_load:
                    min_load = load
                    best_machine_idx = idx

            return best_machine_idx, self.machines[best_machine_idx]

    def online_machine(self, machine_id=None):
        """主机上线"""
        with self.mtx:
            if machine_id is not None:
                # 将指定主机上线
                if machine_id in self.offline_machines:
                    self.offline_machines.remove(machine_id)
                    self.online_machines.append(machine_id)
                    self.machines[machine_id].reset_load()
                    logger.info(f"主机[{machine_id}]已上线")
            else:
                # 将所有离线主机上线
                self.online_machines.extend(self.offline_machines)
                self.offline_machines = []
                for idx in self.online_machines:
                    self.machines[idx].reset_load()
                logger.info("所有主机已上线")

    def offline_machine(self, machine_id):
        """主机离线"""
        with self.mtx:
            if machine_id in self.online_machines:
                self.online_machines.remove(machine_id)
                self.offline_machines.append(machine_id)
                self.machines[machine_id].reset_load()
                logger.info(f"主机[{machine_id}]已离线")

    def show_machines(self):
        """显示当前主机状态（用于调试）"""
        with self.mtx:
            online = ", ".join([f"{i}:{self.machines[i]}" for i in self.online_machines])
            offline = ", ".join([f"{i}:{self.machines[i]}" for i in self.offline_machines])
            logger.info(f"在线主机: [{online}]")
            logger.info(f"离线主机: [{offline}]")